/*
 * @Author: zhangzhen
 * @Date: 2022-12-30 09:13:41
 * @LastEditors: zhangzhen
 * @LastEditTime: 2023-03-15 18:59:55
 *
 */
import React, {FC, useContext, useCallback} from 'react';
import {Button,message} from 'antd';
import {useDrag, DragSourceMonitor} from 'react-dnd';
import {FormContext} from '../context';
import styles from './styles.module.scss';
import {buttonList, expendButtonList, ItemTypes, getId} from '../constant';

const ButtonItem: FC<any> = ({
    item,
    formConTextValue,
    setValue,
    setFormConTextValue,
    isEditing,
    setCurrentIndex,
    setCurrentItem,
    currentItem
}) => {
    // 元素拖拽事件
    const [{opacity}, drag] = useDrag({
        // type: 自定义一个名称。拖动的 type 和放置的 type 保持一致。
        // item:参数传递。拖动时的数据能够传递到放置区。
        // collect: 收集监听整个拖动事件的状态数据，比如是否正在进行拖动、拖动偏移量等数据。可以通过源代码获取完整的数据。
        // end: 拖动结束时执行的方法。
        // canDrag: 指定当前是否允许拖动。若希望始终允许被拖动，则可以忽略此方法。

        type: ItemTypes.Field,

        item() {
            // 不在编辑状态返回空数据
            if (!isEditing) {
                return null;
            }

             // 控件名称必填
             if (currentItem?.key && !currentItem.label) {
                message.error('请填写控件名称');
                return null;
            }
            // 在拖动操作开始时触发
            const useless = formConTextValue.find(
                (formConTextValueItem: any) =>
                    formConTextValueItem.key === 'dragPlaceholder',
            );
            // 拖拽开始时，向 cardList 数据源中插入一个占位的元素，如果占位元素已经存在，不再重复插入
            if (!useless) {
                setFormConTextValue([
                    ...formConTextValue,
                    {key: 'dragPlaceholder'},
                ]);
            }

            // 生成新字段名称
            return {...item.value, name: getId(item.id)};
        },
        /**
         * 拖拽结束时，判断是否将拖拽元素放入了目标接收组件中
         */
        end(_: unknown, monitor: DragSourceMonitor) {
            // 不在编辑状态直接return
            if (monitor.getItem() === null) return;

            const uselessIndex = formConTextValue.findIndex(
                (formConTextValueItem: any) =>
                    formConTextValueItem.key === 'dragPlaceholder',
            );
            /**
             * 拖拽结束时，判断是否将拖拽元素放入了目标接收组件中
             *  1、如果是，则使用真正传入的元素代替占位元素
             *  2、如果否，则将占位元素删除
             */

            const cloneValue = [...formConTextValue];
            if (monitor.didDrop()) {
                cloneValue.splice(uselessIndex, 1, {
                    ...monitor.getItem(),
                });
                setValue(cloneValue);
                setCurrentIndex(uselessIndex);
                setCurrentItem(monitor.getItem());
            } else {
                cloneValue.splice(uselessIndex, 1);
                // 更新数据源
                setFormConTextValue(cloneValue);
            }
        },

        collect: (monitor: any) => ({
            opacity: monitor.isDragging() ? 0.5 : 1,
        }),
    });

    return (
        <Button
            key={item.id}
            ref={drag}
            style={{opacity}}
            onClick={() => {
                if (!isEditing) {
                    return;
                }

                  // 控件名称必填
                  if (currentItem?.key && !currentItem.label) {
                    message.error('请填写控件名称');
                    return;
                }
                const cloneValue = [...formConTextValue];
                cloneValue.push({...item.value, name: getId(item.id)});
                setValue(cloneValue);
            }}>
            {item.name}
        </Button>
    );
};

const Left: FC<{isEdit: boolean}> = ({isEdit}) => {
    const {
        setFormConTextValue,
        formConTextValue,
        setCurrentItem,
        currentItem,
        setCurrentIndex,
        isEditing,
    } = useContext(FormContext);

    // 元素点击事件
    const setValue = useCallback(
        (value: any) => {
            setFormConTextValue(value);
            setCurrentItem(value[value.length - 1]);
            setCurrentIndex(value.length - 1);
        },
        [setCurrentIndex, setCurrentItem, setFormConTextValue],
    );

    return (
        <div
            className={styles.leftBox}
            style={isEdit ? {} : {pointerEvents: 'none'}}>
            <div>基础控件</div>
            <div className={styles.basicCom}>
                {buttonList.map((item) => (
                    <ButtonItem
                        key={item.id}
                        item={item}
                        formConTextValue={formConTextValue}
                        setValue={setValue}
                        setFormConTextValue={setFormConTextValue}
                        isEditing={isEditing}
                        setCurrentIndex={setCurrentIndex}
                        setCurrentItem={setCurrentItem}
                        currentItem={currentItem}
                    />
                ))}
            </div>
            <div>扩展控件</div>
            <div className={styles.basicCom}>
                {expendButtonList.map((item) => (
                    <ButtonItem
                        key={item.id}
                        item={item}
                        formConTextValue={formConTextValue}
                        setValue={setValue}
                        setFormConTextValue={setFormConTextValue}
                        isEditing={isEditing}
                        setCurrentIndex={setCurrentIndex}
                        setCurrentItem={setCurrentItem}
                        currentItem={currentItem}
                    />
                ))}
            </div>
        </div>
    );
};

export default Left;
